﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ElfTyping.Animations;
using ElfTyping.Cards;

namespace ElfTyping.General
{
    public struct PuzzlePiece
    {
        public int ID { get; set; }
        public PuzzlePieceManager.PuzzlePieceCollection Collection { get; set; }

        public PuzzlePiece(int id, PuzzlePieceManager.PuzzlePieceCollection collection) 
            : this()
        {
            ID = id;
            Collection = collection;
        }
    }

    public class PuzzlePieceManager
    {
        Dictionary<int, PuzzlePieceCollection> CollectionMap = new Dictionary<int, PuzzlePieceCollection>();

        Random random = new Random();

        private static PuzzlePieceManager _singleton = null;
        public static PuzzlePieceManager GetManager()
        {
            if (_singleton == null)
            {
                _singleton = new PuzzlePieceManager();
            }

            return _singleton;
        }

        private PuzzlePieceManager()
        {
            CollectionMap.Add(1, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Demon));
            CollectionMap.Add(2, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Demon));
            CollectionMap.Add(3, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Demon));
            CollectionMap.Add(4, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Elf));
            CollectionMap.Add(5, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Elf));
            CollectionMap.Add(6, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Elf));
            CollectionMap.Add(7, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Tan));
            CollectionMap.Add(8, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Tan));
            CollectionMap.Add(9, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.Tan));
            CollectionMap.Add(10, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.White));
            CollectionMap.Add(11, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.White));
            CollectionMap.Add(12, new PuzzlePieceCollection(new Animation(@"Textures\CampState\Camp_Background_4_3"), HaremType.White));
        }

        public PuzzlePiece GenerateRandomPuzzlePiece()
        {
            List<PuzzlePiece> availablePieces = new List<PuzzlePiece>();
            foreach (PuzzlePieceCollection collection in CollectionMap.Values) {
                availablePieces.AddRange(collection.AvailablePieces);
            }

            return availablePieces.OrderBy(piece => random.Next()).First();
        }

        public void FoundPiece(PuzzlePiece piece)
        {
            piece.Collection.FoundPieces.Add(piece.ID);
        }

        public List<string> SerializeToList()
        {
            List<string> result = new List<string>();
            
            foreach (KeyValuePair<int, PuzzlePieceCollection> collection in CollectionMap)
            {
                string foundPieces = collection.Value.FoundPieces
                    .Aggregate(new StringBuilder(), (builder, next) => builder.Append(next))
                    .ToString();
                result.Add(string.Format("{0}-{1}", collection.Key, foundPieces));
            }

            return result;
        }

        public void DeserializeFromList(List<string> list)
        {
            //CollectionMap = new Dictionary<int, PuzzlePieceCollection>();
            foreach (string collection in list)
            {
                string[] idAndFound = collection.Split('-');
                HashSet<int> foundPieces = new HashSet<int>();

                for (int c = 0; c < idAndFound[1].Length; c++)
                {
                    foundPieces.Add(int.Parse(idAndFound[1].Substring(c, 1)));
                }

                CollectionMap[int.Parse(idAndFound[0])].FoundPieces = foundPieces;
            }
        }

        public class PuzzlePieceCollection
        {
            public Animation Image { get; set; }
            public HaremType HaremType { get; set; }
            
            public int TotalPieces { get; set; }            
            public int CardsRewarded { get; set; }

            public HashSet<int> FoundPieces { get; set; }

            public HashSet<PuzzlePiece> AvailablePieces
            {
                get
                {
                    HashSet<PuzzlePiece> result = new HashSet<PuzzlePiece>();
                    for (int i = 1; i <= 5; i++)
                    {
                        if (!FoundPieces.Contains(i))
                        {
                            result.Add(new PuzzlePiece(i, this));
                        }
                    }
                    return result;
                }
            }

            public PuzzlePieceCollection(Animation image, HaremType haremType, int totalPieces, int cardsRewarded)
            {
                Image = image;
                HaremType = haremType;
                TotalPieces = totalPieces;
                CardsRewarded = cardsRewarded;
                FoundPieces = new HashSet<int>();
            }

            public PuzzlePieceCollection(Animation image, HaremType haremType)
                : this(image, haremType, 6, 1) { }
        }
    }
}
